#include "Brick.h"
#include <PA9.h>,
int Brick::counter = 0;

Brick::Brick(void* _texture, int _width, int _height,int _textureType, int _paletteNumber, int _x, int _y)
:width(_width), height(_height),position(_x,_y)/*x(_x),y(_y)*/
{
	
	positionMinus1 = Vector2D(_x,_y);
	mass = 1;
	selected = false;
	tolerance = false; //in pixel;
	flying = false;
	counter++;
	number=counter;
	gfx = PA_3DCreateTex((void*)_texture, width, height,_textureType);	
	PA_3DCreateSpriteFromTex(counter, 					// Sprite number
							gfx, 				// Gfx...
							width, height, 				// Width, Height
							_paletteNumber,			 // Palette
							position.x,position.y/*x,y*/); // X, Y SPRITE CENTER /**/

}
void Brick::tick(float dt,float dtMinus1,Vector2D stylusPosition,Vector2D stylusVelocity, bool stylusHeld, bool stylusPreviouslyHeld)
{
		
		if(selected && stylusHeld && stylusPreviouslyHeld)
		{
			followStylus(stylusPosition);
		}
		else if(stylusHeld && !stylusPreviouslyHeld && isUnderStylus(stylusPosition,true))
		{
			linkToStylus(stylusPosition);
			selected = true;
		}
		else
		{
			selected = false;
			if(isFlying())
			{
				
				Vector2D gravity = Vector2D(Vector2D(0,1),50);
				Vector2D forceSum = gravity;
				Vector2D acceleration = forceSum;
				/*if(position.x+width/2>180 && velocity.x!=0)
				{
					int orientation = 1;
					if(acceleration.x>0)
						orientation = -1;
					Vector2D friction = Vector2D(Vector2D(orientation,0.01),0.3);
					forceSum = forceSum+friction;			
				}*/
				acceleration = acceleration*(1/float(mass));
				//Verlet integration 2 : xi+1 = xi + (xi - xi-1) * (dti / dti-1) + a * dti * dti
				//position = position +(position - positionMinus1)*(dt/dtMinus1)+ acceleration*dt*dt;
				
				//Verlet Integration 2 : xi+1 = xi + (xi - xi-1) + a * dt * dt
				checkCollision(acceleration);
				position = position +(position-positionMinus1)+(acceleration*(dt*dt));	
				
			}
			else
			{
			}
		}
		regulateCoordinates();
		positionMinus1 = position;
		PA_3DSetSpriteXY(number, position.x, position.y);
}
void Brick::tick(Vector2D stylusPosition,Vector2D stylusVelocity, bool stylusHeld, bool stylusPreviouslyHeld)
{
		
		if(selected && stylusHeld && stylusPreviouslyHeld)
		{
			followStylus(stylusPosition);
			velocity = stylusVelocity;
		}
		else if(stylusHeld && !stylusPreviouslyHeld && isUnderStylus(stylusPosition,true))
		{
			linkToStylus(stylusPosition);
			selected = true;
		}
		else
		{
			selected = false;
			if(isFlying())
			{
				position = position+velocity;
				Vector2D gravity = Vector2D(Vector2D(0,1),0.3);
				if(position.x+width/2>180 && velocity.x!=0)
				{
					int orientation = 1;
					if(velocity.x>0)
						orientation = -1;
					Vector2D friction = Vector2D(Vector2D(orientation,0),0.03);
					velocity=velocity+friction;
				}
				velocity=velocity+gravity;
			}
			else
			{
			}
		}
		regulateCoordinates();
		positionMinus1 = position;
		PA_3DSetSpriteXY(number, position.x, position.y);	
}
void Brick::followStylus(Vector2D stylus)
{
	position = stylus+offset;
}
void Brick::linkToStylus(Vector2D stylus)
{
	offset = position - stylus;
}
bool Brick::isUnderStylus(Vector2D stylus, bool useTolerance)
{
	int tol = useTolerance * 10;
	return (stylus.x<position.x+width/2+tol && stylus.x>position.x-width/2-tol) &&(stylus.y<position.y+height/2+tol && stylus.y>position.y-height/2-tol);
}

void Brick::followStylus(int stylusX, int stylusY)
{
	Vector2D stylus = Vector2D(stylusX,stylusY);
	position = stylus+offset;
}
void Brick::linkToStylus(int stylusX, int stylusY)
{
	offset = position - Vector2D(stylusX,stylusY);
}
bool Brick::isUnderStylus(int stylusX, int stylusY, bool useTolerance)
{
	int tol = useTolerance * 10;
	return (stylusX<position.x+width/2+tol && stylusX>position.x-width/2-tol) &&(stylusY<position.y+height/2+tol && stylusY>position.y-height/2-tol);
}
void Brick::regulateCoordinates()
{
		if ((position.x+width/2)>256)
		{
			position.x=256-width/2;
			velocity.x = -velocity.x;
		}
		else if((position.x-width/2)<0)
		{
			position.x=width/2;
			velocity.x = -velocity.x;

		}
		if((position.y+height/2)>192)
		{
			position.y = (192-height/2);
			velocity.y = -0.5*velocity.y;

		}
		else if ((position.y-height/2)<0)
		{
			position.y=height/2;
			velocity.y = 0;

		}

}
void Brick::checkCollision(Vector2D& acceleration) 
{
		float restitution = 1;
		if ((position.x+width/2)>256 || (position.x-width/2)<0)
		{
			acceleration.x = - acceleration.x*restitution;				
		}
		else if((position.y+height/2)>192 || (position.y-height/2)<0)
		{
			acceleration.y = - acceleration.y*restitution;
		}
		
		
}
bool Brick::collidesWith(float topCornerX,float topCornerY,float _width, float _height)
{
	// this collides with the rectangle from the left
	bool collideFromTheLeft = ((position.x+width/2)>topCornerX) && ((position.x+width/2)<(topCornerX+_width));
	bool collideFromTheRight = ((position.x-width/2)>topCornerX) && ((position.x-width/2)<(topCornerX+_width));
	if(!collideFromTheRight && !collideFromTheLeft)
	{		
		return false;
	}
	bool collideFromTheTop = ((position.y+height/2)>=topCornerY) && ((position.y+height/2)<=(topCornerY+_height));
	bool collideFromTheBottom = ((position.y-height/2)>=topCornerY) && ((position.y-height/2)<=(topCornerY+_height));
	if(!collideFromTheTop && !collideFromTheBottom)
	{
		return false;
	}
	//correct vertical position
	Vector2D corrector;
	if(collideFromTheRight)
	{
		corrector.x = position.x+width/2 - topCornerX;
	}
	else
	{
		corrector.x = position.x-width/2 - topCornerX+_width;
	}
	//correct horizontal position
	if (collideFromTheBottom)
	{
		corrector.y = position.y+height/2+topCornerX+_height;
	}
	else
	{
		corrector.y = position.y-height/2-topCornerY;
	}
	position = position+corrector;
	//correct velocity
	if(isFlying())
	{
		velocity.y= -velocity.y;
		velocity.x= -velocity.x;
	}
	PA_3DSetSpriteXY(number, position.x, position.y);
	return true;
}
bool Brick::isFlying()
{
	return true;//(velocity.x>0.1 || velocity.x<-0.1) || velocity.y>0.1;
}
